﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Configuration;
using System.Reflection;
using GBlog.Core.Data;
using GBlog.Core.Service;
using GBlog.Core.Service.Default;
using System.Web.Mvc;
using System.Web.Routing;
using Autofac;
using Autofac.Features.ResolveAnything;
using Autofac.Integration.Web;
using Autofac.Integration.Web.Mvc;
using GBlog.Core.Data.Default;
using GBlog.Core.Infrastructure;
using System.Web.Security;
using GBlog.Core.Entities;
using System.Web.Script.Serialization;
using System.IO;
using System.Data.Entity;

namespace GBlog.Core
{
    public abstract class GApplication : HttpApplication, IContainerProviderAccessor
    {
        ContainerBuilder Builder = new ContainerBuilder();
        public override void Init()
        {
            base.Init();
            List<Type> types = GetType().Assembly.GetTypes().Where(t => t.IsClass && typeof(IHttpModule).IsAssignableFrom(t) && t.Namespace == "GBlog.Core.Modules").ToList();
            foreach (var type in types)
            {
                IHttpModule module = (IHttpModule)Activator.CreateInstance(type);
                module.Init(this);
            }
        }

        protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
        {
            HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
            if (authCookie != null)
            {
                FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
                JavaScriptSerializer serializer = new JavaScriptSerializer();
                User serializeModel = serializer.Deserialize<User>(authTicket.UserData);
                serializeModel.CreateAuth();
                HttpContext.Current.User = serializeModel;
            }
        }

        protected IContainer RegisterDependencies()
        {
            Builder.RegisterModelBinders(Assembly.GetExecutingAssembly());
            Builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>));
            RegisterServices.RegisterAll(Builder);

            var container = Builder.Build();
            _ContainerProvider = new ContainerProvider(container);
            return container;
        }

        protected void RegisterController(Type type)
        {
            Builder.RegisterControllers(type.Assembly).PropertiesAutowired();
        }

        internal protected virtual void Application_Start()
        {
            Database.SetInitializer(new GInitializer());
            var container = RegisterDependencies();
            DependencyResolver.SetResolver(new Dependency(container));

            FilterProviders.Providers.Remove(FilterProviders.Providers.Single(f => f is FilterAttributeFilterProvider));
            FilterProviders.Providers.Add(new GFilterProvider(new ContainerProvider(container)));

            HtmlHelper.ClientValidationEnabled = true;
            HtmlHelper.UnobtrusiveJavaScriptEnabled = true;

            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new GViewEngine(DependencyResolver.Current.GetService<IThemeService>()));
        }

        internal protected void Application_BeginRequest(object sender, EventArgs e)
        {
            var path = Request.Url.AbsolutePath;
            var verbIsGet = string.Equals(Request.HttpMethod, "GET", StringComparison.CurrentCultureIgnoreCase);
            if (!verbIsGet || !path.Any(c => char.IsUpper(c))) return;
            Response.RedirectPermanent(path.ToLowerInvariant() + Request.Url.Query);
        }

        internal protected void Application_Error(object sender, EventArgs e)
        {
            if (!HttpContext.Current.IsCustomErrorEnabled)
                return;
            var exception = Server.GetLastError();
            var httpException = new HttpException(null, exception);
            var routeData = new RouteData();
            routeData.Values.Add("controller", "Error");
            routeData.Values.Add("action", "Index");
            routeData.Values.Add("httpException", httpException);
            Server.ClearError();
            var errorController = ControllerBuilder.Current.GetControllerFactory().CreateController(new RequestContext(new HttpContextWrapper(Context), routeData), "Error");
            errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
        }

        static IContainerProvider _ContainerProvider;
        public IContainerProvider ContainerProvider
        {
            get { return _ContainerProvider; }
        }
    }
}